package com.lleice.service.service.sys.impl;

import java.util.List;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.stream.Collectors;

import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.lleice.common.enums.ExceptionEnum;
import com.lleice.common.exception.BusinessException;
import com.lleice.common.utils.AssertUtil;
import com.lleice.common.utils.TreeListUtil;
import com.lleice.service.dto.ResourceRoleTreeDto;
import com.lleice.service.dto.ResourceRoleTreeParentDto;
import com.lleice.service.dto.ResourceTreeParentDto;
import com.lleice.service.entity.sys.SysResource;
import com.lleice.service.mapper.sys.SysResourceMapper;
import com.lleice.service.mapstruct.SysResourceConverMapper;
import com.lleice.service.qo.sys.ResourceReq;
import com.lleice.service.service.sys.ISysResourceService;

import cn.hutool.core.collection.ListUtil;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.StrUtil;

/**
 * <p>
 * 菜单资源表 服务实现类
 * </p>
 *
 * @author lizihao
 * @since 2020-11-18
 */
@Service
public class SysResourceServiceImpl extends ServiceImpl<SysResourceMapper, SysResource> implements ISysResourceService {
	
    /**
     * 去重
     * @param <T>
     * @param keyExtractor
     * @return
     */
    private static <T> Predicate<T> distinctByKey(Function<? super T, ?> keyExtractor) {
    Set<Object> seen = ConcurrentHashMap.newKeySet();
    return t -> seen.add(keyExtractor.apply(t));
    }

	@Override
	public List<ResourceRoleTreeParentDto> selectUserResourceList(Long userId)
			throws Exception {
		return TreeListUtil.getTreeList(this.baseMapper.selectUserResourceList(userId).stream().filter(distinctByKey(ResourceRoleTreeDto::getId)).collect(Collectors.toList()), 
				MapUtil.of(new String[][] {
				     {"nameKey", "resourceName"},
				     {"weightKey", "sortNum"},
				     {"idKey", "id"},
				     {"parentIdKey", "parentId"}
				}), ListUtil.of("parentId","resourceCode","resourcePath","resourceType"), ResourceRoleTreeParentDto.class);
	}

	@Override
	@Transactional(rollbackFor = Exception.class)
	public void saveOrUpdateUser(ResourceReq resourceReq) throws Exception {
		if(StrUtil.isBlank(resourceReq.getId())) {
			SysResource resource = SysResourceConverMapper.INSTANCES.resourceReqToSysResource(resourceReq);
			resource.setSortNum(this.baseMapper.getMaxOrderNum()+1);
			this.baseMapper.insert(resource);
		}else {
			AssertUtil.isTrue(resourceReq.getId().equals(resourceReq.getParentId()),() -> new BusinessException(ExceptionEnum.REPEAT_VALUE));
			SysResource resource = SysResourceConverMapper.INSTANCES.resourceReqToSysResource(resourceReq);
			this.baseMapper.updateById(resource);
		}
		
	}

	@Override
	public List<ResourceTreeParentDto> getAllResource() throws Exception{
		return TreeListUtil.getTreeList(this.baseMapper.getAllResource(), 
				MapUtil.of(new String[][] {
				     {"nameKey", "resourceName"},
				     {"weightKey", "sortNum"},
				     {"idKey", "id"},
				     {"parentIdKey", "parentId"}
				}), ListUtil.of("parentId","isShow"), ResourceTreeParentDto.class);
	}

	@Override
	public List<ResourceTreeParentDto> getAllResourceWithUser(Long roleId) throws Exception{
		return TreeListUtil.getTreeList(this.baseMapper.getAllResourceWithUser(roleId), 
				MapUtil.of(new String[][] {
				     {"nameKey", "resourceName"},
				     {"weightKey", "sortNum"},
				     {"idKey", "id"},
				     {"parentIdKey", "parentId"}
				}), ListUtil.of("parentId","isShow"), ResourceTreeParentDto.class);
	}

}
